home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / godelqc5.zip / COMBAT.QC < prev    next >
Text File  |  1996-09-18  |  7KB  |  299 lines

  1.  
  2. //prototypes
  3. void() T_MissileTouch;
  4. void() info_player_start;
  5. void(entity targ, entity inflictor,entity attacker) ClientObituary;
  6. void(entity targ,entity inflictor, float vel) DamageGib;
  7.  
  8. void() monster_death_use;
  9.  
  10. //============================================================================
  11.  
  12. /*
  13. ============
  14. CanDamage
  15.  
  16. Returns true if the inflictor can directly damage the target.  Used for
  17. explosions and melee attacks.
  18. ============
  19. */
  20. float(entity targ, entity inflictor) CanDamage =
  21. {
  22. // bmodels need special checking because their origin is 0,0,0
  23.     if (targ.movetype == MOVETYPE_PUSH)
  24.     {
  25.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  26.         if (trace_fraction == 1)
  27.             return TRUE;
  28.         if (trace_ent == targ)
  29.             return TRUE;
  30.         return FALSE;
  31.     }
  32.     
  33.     traceline(inflictor.origin, targ.origin, TRUE, self);
  34.     if (trace_fraction == 1)
  35.         return TRUE;
  36.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  37.     if (trace_fraction == 1)
  38.         return TRUE;
  39.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  40.     if (trace_fraction == 1)
  41.         return TRUE;
  42.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  43.     if (trace_fraction == 1)
  44.         return TRUE;
  45.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  46.     if (trace_fraction == 1)
  47.         return TRUE;
  48.  
  49.     return FALSE;
  50. };
  51.  
  52.  
  53. /*
  54. ============
  55. Killed
  56. ============
  57. */
  58. void(entity targ, entity inflictor,entity attacker) Killed =
  59. {
  60.     local entity oself;
  61.  
  62.     oself = self;
  63.     self = targ;
  64.     
  65.     if (self.health < -99)
  66.         self.health = -99; // don't let sbar look bad if a player
  67.  
  68.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  69.     {       // doors, triggers, etc
  70.         self.th_die ();
  71.         self = oself;
  72.         return;
  73.     }
  74.  
  75.     self.enemy = attacker;
  76.  
  77. // bump the monster counter
  78.     if (self.flags & FL_MONSTER)
  79.     {
  80.         killed_monsters = killed_monsters + 1;
  81.         WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  82.     }
  83.  
  84.  
  85.     self.takedamage = DAMAGE_NO;
  86.     self.touch = SUB_Null;
  87.  
  88.     monster_death_use();
  89.     self.th_die ();
  90.     ClientObituary(self, inflictor,attacker);
  91.     
  92.     self = oself;
  93. };
  94.  
  95.  
  96. /*
  97. ============
  98. T_Damage
  99.  
  100. The damage is coming from inflictor, but get mad at attacker
  101. This should be the only function that ever reduces health.
  102. ============
  103. */
  104. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  105. {
  106.     local   vector  dir;
  107.     local   entity  oldself;
  108.     local   entity  found;
  109.     local   float   save;
  110.     local   float   take;
  111.  
  112.     if (!targ.takedamage)
  113.         return;
  114.  
  115. // used by buttons and triggers to set activator for target firing
  116.     damage_attacker = attacker;
  117.  
  118. // Godel qc: used for Quake-TI mode
  119. // check for quad damage powerup on the attacker
  120.     if (teamplay == 6 && (targ.flags & FL_AM_IT) && (numplayers>2)) 
  121.         damage = damage * (numplayers - 1);
  122.     else if (attacker.super_damage_finished > time)
  123.         damage = damage * 4;
  124.     if(teamplay==7 && world_flag && (targ.classname=="player")) damage = 0;
  125.  
  126. // save damage based on the target's armor level
  127.  
  128.     save = ceil(targ.armortype*damage);
  129.     if (save >= targ.armorvalue)
  130.     {
  131.         save = targ.armorvalue;
  132.         targ.armortype = 0;     // lost all armor
  133.         targ.items=targ.items-(targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  134.     }
  135.     
  136.     targ.armorvalue = targ.armorvalue - save;
  137.     take = ceil(damage-save);
  138.  
  139. // add to the damage total for clients, which will be sent as a single
  140. // message at the end of the frame
  141. // FIXME: remove after combining shotgun blasts?
  142.     if (targ.flags & FL_CLIENT)
  143.     {
  144.         targ.dmg_take = targ.dmg_take + take;
  145.         targ.dmg_save = targ.dmg_save + save;
  146.         targ.dmg_inflictor = inflictor;
  147.     }
  148.  
  149. // figure momentum add
  150.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  151.     {
  152.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  153.         dir = normalize(dir);
  154.         targ.velocity = targ.velocity + dir*damage*8;
  155.     }
  156.  
  157. // check for godmode or invincibility
  158.     if (targ.flags & FL_GODMODE)
  159.         return;
  160.     if (targ.invincible_finished >= time)
  161.     {
  162.         if (self.invincible_sound < time)
  163.         {
  164.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  165.             self.invincible_sound = time + 2;
  166.         }
  167.         return;
  168.     }
  169.  
  170. // team play damage avoidance mode 0 only
  171.     if ( (teamplay == 1 ) && (targ.team > 0)&&(targ.team == attacker.team) )
  172.         return;
  173.         
  174. //    Godel qc: make target gib on taking damage
  175.     DamageGib(targ,inflictor,take);
  176.  
  177. // do the damage
  178.     targ.health = targ.health - take;
  179.             
  180.     if (targ.health <= 0)
  181.     {
  182.         Killed (targ, inflictor,attacker);
  183.         return;
  184.     }
  185.  
  186. // react to the damage
  187.     oldself = self;
  188.     self = targ;
  189.  
  190.  
  191.     if ( (self.flags & FL_MONSTER) && attacker != world) {
  192.     // get mad unless of the same class (except for soldiers)
  193.         if (self != attacker && attacker != self.enemy) {
  194.             if ( (self.classname != attacker.classname) 
  195.             || (self.classname == "monster_army" ) )
  196.             {
  197.                 if (self.enemy.classname == "player")
  198.                     self.oldenemy = self.enemy;
  199.                 self.enemy = attacker;
  200.                 FoundTarget ();
  201.             }
  202.         }
  203.     }
  204.  
  205.  
  206.     if (self.th_pain)
  207.     {
  208.         self.th_pain (attacker, take);
  209.     // nightmare mode monsters don't go into pain frames often
  210.         if (skill == 3)
  211.             self.pain_finished = time + 5;          
  212.     }
  213.     self = oldself;
  214. };
  215.  
  216. /*
  217. ============
  218. T_RadiusDamage
  219. ============
  220. */
  221. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  222. {
  223.     local   float   points;
  224.     local   entity  head;
  225.     local   vector  org;
  226.  
  227.     head = findradius(inflictor.origin, damage+40);
  228.     
  229.     while (head) {
  230.         if (head != ignore) {
  231.             org = head.origin + (head.mins + head.maxs)*0.5;
  232.             points = 0.5*vlen (inflictor.origin - org);
  233.             if (points < 0) points = 0;
  234.             points = damage - points;
  235.             if (head == attacker) points = points * 0.5;
  236.  
  237. //    Godel qc: only explode if it does a decent amount of damage.
  238.             if (points>50){
  239.                 if (((head.classname=="grenade") || (head.classname=="missile")
  240.               || (head.classname=="pipebomb")) && (head.nextthink > time+0.15))
  241.                     head.nextthink=time+0.15;
  242.                 if (head.classname=="tripbomb") head.health=2;
  243.             }
  244.             if (head.takedamage)
  245.             {
  246.                 if (points > 0)
  247.                 {
  248.                     if (CanDamage (head, inflictor))
  249.                     {       // shambler takes half damage from all explosions
  250.                         if (head.classname == "monster_shambler")                                               
  251.                             T_Damage (head, inflictor, attacker, points*0.5);
  252.                         else
  253.                             T_Damage (head, inflictor, attacker, points);
  254.                     }
  255.                 }
  256.             }
  257.         }
  258.         head = head.chain;
  259.     }
  260. };
  261.  
  262. /*
  263. ============
  264. T_BeamDamage
  265. ============
  266. */
  267. void(entity attacker, float damage) T_BeamDamage =
  268. {
  269.     local   float   points;
  270.     local   entity  head;
  271.     
  272.     head = findradius(attacker.origin, damage+40);
  273.     
  274.     while (head)
  275.     {
  276.         if (head.takedamage)
  277.         {
  278.             points = 0.5*vlen (attacker.origin - head.origin);
  279.             if (points < 0)
  280.                 points = 0;
  281.             points = damage - points;
  282.             if (head == attacker)
  283.                 points = points * 0.5;
  284.             if (points > 0)
  285.             {
  286.                 if (CanDamage (head, attacker))
  287.                 {
  288.                     if (head.classname == "monster_shambler")                                               
  289.                         T_Damage (head, attacker, attacker, points*0.5);
  290.                     else
  291.                         T_Damage (head, attacker, attacker, points);
  292.                 }
  293.             }
  294.         }
  295.         head = head.chain;
  296.     }
  297. };
  298.  
  299.